using Engine;
using Engine.Graphics;
using System;
using System.Collections.Generic;

namespace Game
{
	public class LightbulbBlock : MountedElectricElementBlock, IPaintableBlock
	{
		public const int Index = 139;

		private BlockMesh m_standaloneBulbBlockMesh = new BlockMesh();

		private BlockMesh m_standaloneSidesBlockMesh = new BlockMesh();

		private BlockMesh[] m_bulbBlockMeshes = new BlockMesh[6];

		private BlockMesh[] m_bulbBlockMeshesLit = new BlockMesh[6];

		private BlockMesh[] m_sidesBlockMeshes = new BlockMesh[6];

		private BoundingBox[][] m_collisionBoxes = new BoundingBox[6][];

		private Color m_copperColor = new Color(118, 56, 32);

		public override void Initialize()
		{
			Model model = ContentManager.Get<Model>("Models/Lightbulbs");
			Matrix boneAbsoluteTransform = BlockMesh.GetBoneAbsoluteTransform(model.FindMesh("Top").ParentBone);
			Matrix boneAbsoluteTransform2 = BlockMesh.GetBoneAbsoluteTransform(model.FindMesh("Sides").ParentBone);
			for (int i = 0; i < 6; i++)
			{
				Matrix m = (i >= 4) ? ((i != 4) ? (Matrix.CreateRotationX((float)Math.PI) * Matrix.CreateTranslation(0.5f, 1f, 0.5f)) : Matrix.CreateTranslation(0.5f, 0f, 0.5f)) : (Matrix.CreateRotationX((float)Math.PI / 2f) * Matrix.CreateTranslation(0f, 0f, -0.5f) * Matrix.CreateRotationY((float)i * (float)Math.PI / 2f) * Matrix.CreateTranslation(0.5f, 0.5f, 0.5f));
				m_bulbBlockMeshes[i] = new BlockMesh();
				m_bulbBlockMeshes[i].AppendModelMeshPart(model.FindMesh("Top").MeshParts[0], boneAbsoluteTransform * m, makeEmissive: false, flipWindingOrder: false, doubleSided: false, flipNormals: false, Color.White);
				m_bulbBlockMeshes[i].TransformTextureCoordinates(Matrix.CreateTranslation(0.1875f, 0.25f, 0f));
				m_bulbBlockMeshesLit[i] = new BlockMesh();
				m_bulbBlockMeshesLit[i].AppendModelMeshPart(model.FindMesh("Top").MeshParts[0], boneAbsoluteTransform * m, makeEmissive: true, flipWindingOrder: false, doubleSided: false, flipNormals: false, new Color(255, 255, 230));
				m_bulbBlockMeshesLit[i].TransformTextureCoordinates(Matrix.CreateTranslation(0.9375f, 0f, 0f));
				m_sidesBlockMeshes[i] = new BlockMesh();
				m_sidesBlockMeshes[i].AppendModelMeshPart(model.FindMesh("Sides").MeshParts[0], boneAbsoluteTransform2 * m, makeEmissive: false, flipWindingOrder: false, doubleSided: true, flipNormals: false, Color.White);
				m_sidesBlockMeshes[i].TransformTextureCoordinates(Matrix.CreateTranslation(0.9375f, 0.1875f, 0f));
				m_collisionBoxes[i] = new BoundingBox[1]
				{
					m_sidesBlockMeshes[i].CalculateBoundingBox()
				};
			}
			Matrix m2 = Matrix.CreateRotationY(-(float)Math.PI / 2f) * Matrix.CreateRotationZ((float)Math.PI / 2f);
			m_standaloneBulbBlockMesh.AppendModelMeshPart(model.FindMesh("Top").MeshParts[0], boneAbsoluteTransform * m2, makeEmissive: false, flipWindingOrder: false, doubleSided: true, flipNormals: false, Color.White);
			m_standaloneBulbBlockMesh.TransformTextureCoordinates(Matrix.CreateTranslation(0.1875f, 0.25f, 0f));
			m_standaloneSidesBlockMesh.AppendModelMeshPart(model.FindMesh("Sides").MeshParts[0], boneAbsoluteTransform2 * m2, makeEmissive: false, flipWindingOrder: false, doubleSided: true, flipNormals: false, Color.White);
			m_standaloneSidesBlockMesh.TransformTextureCoordinates(Matrix.CreateTranslation(0.9375f, 0.1875f, 0f));
		}

		public override IEnumerable<int> GetCreativeValues()
		{
			yield return Terrain.MakeBlockValue(139);
			int i = 0;
			while (i < 16)
			{
				yield return Terrain.MakeBlockValue(139, 0, SetColor(0, i));
				int num = i + 1;
				i = num;
			}
		}

		public override string GetDisplayName(SubsystemTerrain subsystemTerrain, int value)
		{
			int? color = GetColor(Terrain.ExtractData(value));
			return SubsystemPalette.GetName(subsystemTerrain, color, "Lightbulb");
		}

		public override string GetCategory(int value)
		{
			if (!GetColor(Terrain.ExtractData(value)).HasValue)
			{
				return base.GetCategory(value);
			}
			return "Painted";
		}

		public override int GetFace(int value)
		{
			return GetMountingFace(Terrain.ExtractData(value));
		}

		public override int GetEmittedLightAmount(int value)
		{
			return GetLightIntensity(Terrain.ExtractData(value));
		}

		public override int GetShadowStrength(int value)
		{
			int lightIntensity = GetLightIntensity(Terrain.ExtractData(value));
			return DefaultShadowStrength - 10 * lightIntensity;
		}

		public override BlockPlacementData GetPlacementValue(SubsystemTerrain subsystemTerrain, ComponentMiner componentMiner, int value, TerrainRaycastResult raycastResult)
		{
			BlockPlacementData result = default(BlockPlacementData);
			result.Value = Terrain.MakeBlockValue(139, 0, SetMountingFace(Terrain.ExtractData(value), raycastResult.CellFace.Face));
			result.CellFace = raycastResult.CellFace;
			return result;
		}

		public override void GetDropValues(SubsystemTerrain subsystemTerrain, int oldValue, int newValue, int toolLevel, List<BlockDropValue> dropValues, out bool showDebris)
		{
			int? color = GetColor(Terrain.ExtractData(oldValue));
			dropValues.Add(new BlockDropValue
			{
				Value = Terrain.MakeBlockValue(139, 0, SetColor(0, color)),
				Count = 1
			});
			showDebris = true;
		}

		public override BoundingBox[] GetCustomCollisionBoxes(SubsystemTerrain terrain, int value)
		{
			int mountingFace = GetMountingFace(Terrain.ExtractData(value));
			if (mountingFace >= m_collisionBoxes.Length)
			{
				return null;
			}
			return m_collisionBoxes[mountingFace];
		}

		public override void GenerateTerrainVertices(BlockGeometryGenerator generator, TerrainGeometry geometry, int value, int x, int y, int z)
		{
			int data = Terrain.ExtractData(value);
			int mountingFace = GetMountingFace(data);
			int lightIntensity = GetLightIntensity(data);
			int? color = GetColor(data);
			Color color2 = color.HasValue ? SubsystemPalette.GetColor(generator, color) : m_copperColor;
			if (mountingFace < m_bulbBlockMeshes.Length)
			{
				if (lightIntensity <= 0)
				{
					generator.GenerateMeshVertices(this, x, y, z, m_bulbBlockMeshes[mountingFace], Color.White, null, geometry.SubsetAlphaTest);
				}
				else
				{
					byte r = (byte)(195 + lightIntensity * 4);
					byte g = (byte)(180 + lightIntensity * 5);
					byte b = (byte)(165 + lightIntensity * 6);
					generator.GenerateMeshVertices(this, x, y, z, m_bulbBlockMeshesLit[mountingFace], new Color(r, g, b), null, geometry.SubsetOpaque);
				}
				generator.GenerateMeshVertices(this, x, y, z, m_sidesBlockMeshes[mountingFace], color2, null, geometry.SubsetOpaque);
				generator.GenerateWireVertices(value, x, y, z, mountingFace, 0.875f, Vector2.Zero, geometry.SubsetOpaque);
			}
		}

		public override void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData)
		{
			int? color2 = GetColor(Terrain.ExtractData(value));
			Color c = color2.HasValue ? SubsystemPalette.GetColor(environmentData, color2) : m_copperColor;
			BlocksManager.DrawMeshBlock(primitivesRenderer, m_standaloneSidesBlockMesh, color * c, 2f * size, ref matrix, environmentData);
			BlocksManager.DrawMeshBlock(primitivesRenderer, m_standaloneBulbBlockMesh, color, 2f * size, ref matrix, environmentData);
		}

		public int? GetPaintColor(int value)
		{
			return GetColor(Terrain.ExtractData(value));
		}

		public int Paint(SubsystemTerrain subsystemTerrain, int value, int? color)
		{
			int data = Terrain.ExtractData(value);
			return Terrain.ReplaceData(value, SetColor(data, color));
		}

		public override ElectricElement CreateElectricElement(SubsystemElectricity subsystemElectricity, int value, int x, int y, int z)
		{
			return new LightBulbElectricElement(subsystemElectricity, new CellFace(x, y, z, GetFace(value)), value);
		}

		public override ElectricConnectorType? GetConnectorType(SubsystemTerrain terrain, int value, int face, int connectorFace, int x, int y, int z)
		{
			int face2 = GetFace(value);
			if (face == face2 && SubsystemElectricity.GetConnectorDirection(face2, 0, connectorFace).HasValue)
			{
				return ElectricConnectorType.Input;
			}
			return null;
		}

		public static int GetMountingFace(int data)
		{
			return data & 7;
		}

		public static int SetMountingFace(int data, int face)
		{
			return (data & -8) | (face & 7);
		}

		public static int GetLightIntensity(int data)
		{
			return (data >> 3) & 0xF;
		}

		public static int SetLightIntensity(int data, int intensity)
		{
			return (data & -121) | ((intensity & 0xF) << 3);
		}

		public static int? GetColor(int data)
		{
			if ((data & 0x80) != 0)
			{
				return (data >> 8) & 0xF;
			}
			return null;
		}

		public static int SetColor(int data, int? color)
		{
			if (color.HasValue)
			{
				return (data & -3969) | 0x80 | ((color.Value & 0xF) << 8);
			}
			return data & -3969;
		}
	}
}
